package es.tikitaka.actions.equipos;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.FlushModeType;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.faces.FacesMessages;
import org.richfaces.event.UploadEvent;
import org.richfaces.model.UploadItem;

import es.tikitaka.dao.AniosDicService;
import es.tikitaka.dao.EquipoService;
import es.tikitaka.dao.PartEquipoService;
import es.tikitaka.dao.PartJugadorService;
import es.tikitaka.dao.PosicionDicService;
import es.tikitaka.dictionary.AniosDic;
import es.tikitaka.dictionary.PosicionDic;
import es.tikitaka.domain.Temporada;
import es.tikitaka.domain.equipo.Equipo;
import es.tikitaka.domain.equipo.PartEquipo;
import es.tikitaka.domain.jugador.Jugador;
import es.tikitaka.domain.jugador.PartJugador;

/**
 * 
 * @author Saúl Domínguez
 * @since 2010
 * @category PFC
 */

@Name("equipoAction")
@Scope(ScopeType.SESSION)
public class EquipoAction {

	private int modo;
	private boolean nuevo;

	private Equipo equipo;
	private String nombre;
	private PartEquipo participacion;
	private PartEquipo nextParticipacion;

	private Equipo newEquipo;
	private boolean guardado = false;

	private byte[] foto;

	private List<AniosDic> listaAnios;
	private List<PartEquipo> listaParticipaciones;
	private List<PosicionDic> listaPosiciones;

	private PosicionDic posicion;
	private Integer dorsal;

	// atributos para la búsqueda de jugadores que formen el equipo
	private String buscarJug;
	private int buscarJugEn;
	private boolean nuevoJug = false;
	@DataModel("jugadoresBus")
	private List<PartJugador> jugadoresBus;
	private PartJugador jugadorSel;
	// fin atributos

	@DataModel("jugadoresEquipo")
	private Set<PartJugador> jugadoresEquipo;
	@DataModelSelection("jugadoresEquipo")
	private PartJugador jugadorItem;
	private PartJugador jugadorDelete;

	@In(create = true)
	private AniosDicService aniosService;

	@In(create = true)
	private EquipoService equipoService;

	@In(create = true)
	private EquipoSearch equipoSearch;

	@In(create = true)
	private PartEquipoService partEquipoService;

	@In(create = true)
	private PartJugadorService partJugadorService;

	@In(create = true)
	private PosicionDicService posicionService;

	/**
	 * Constructor por defecto
	 */
	public EquipoAction() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Método para la creación de un nuevo equipo
	 */
	public void nuevoEquipo() {
		newEquipo = new Equipo();
		nuevo = true;
		listaAnios = aniosService.getList();
		guardado = false;
	}

	/**
	 * Método para seleccionar a un equipo de entre los resultados de una
	 * consulta para realizar sobre él las acciones determinadas por el modo de
	 * selección
	 * 
	 * @param team
	 *            Equipo seleccionado
	 * @param md
	 *            modo de selección, edición, consulta, alta o baja
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void selectEquipo(Equipo team, int md) {
		equipo = team;
		nombre = equipo.getNombre();
		modo = md;
		listaAnios = aniosService.getList();
		listaParticipaciones = partEquipoService.getParticipaciones(equipo);
		nuevo = false;

		if (equipoSearch.getTemporada() != null) {
			Temporada t = equipoSearch.getTemporada();
			for (PartEquipo p : listaParticipaciones) {
				if (p.getTemporada().equals(t)) {
					participacion = p;
					jugadoresEquipo = participacion.getM_jugadores();
				}
			}
		}
	}

	/**
	 * 
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void selectTemporada() {
		if (nextParticipacion != null) {
			participacion = (PartEquipo) nextParticipacion;
			jugadoresEquipo = nextParticipacion.getM_jugadores();
		} else {
			jugadoresEquipo = null;
		}
	}

	/**
	 * Método para obtener una fotografía subida por un usuario
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void obtenerFotografia(UploadEvent event) throws Exception {

		UploadItem item = event.getUploadItem();

		foto = item.getData();
		if (foto != null) {
			FacesMessages.instance().add("Escudo subido correctamente");
			if (nuevo) {
				newEquipo.setFoto(foto);
			} else {
				equipo.setFoto(foto);
			}
		} else {
			FacesMessages.instance().add("No se ha subida ningún escudo");
		}

	}

	public void deletePhoto() {
		if (nuevo) {
			if (newEquipo.getFoto() != null) {
				newEquipo.setFoto(null);
				FacesMessages.instance().add("Escudo eliminado correctamente");
			}
		} else {
			if (equipo.getFoto() != null) {
				equipo.setFoto(null);
				FacesMessages.instance().add(
						"Fotografía eliminada correctamente");
			}
		}
	}

	/**
	 * Método para guardar las modificaciones realizadas a un equipo
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void guardar() {
		if (!comprobarNombre()) {
			if (nuevo) {
				guardado = equipoService.save(newEquipo);
			} else {
				if (guardarParticipaciones()) {
					equipo.setNombre(nombre);
					guardado = equipoService.save(equipo);
				}
			}
			if (guardado) {
				FacesMessages.instance().add("Se ha registrado con éxito.");
			} else {
				FacesMessages
						.instance()
						.add(
								"Se ha producido un error y no se ha podido completar el proceso de registro.");
			}
		}
	}

	/**
	 * Método para comprobar que el equipo tiene un nombre y este es válido
	 * 
	 * @return estado de la comprobación (true or false)
	 */
	public boolean comprobarNombre() {

		boolean estado = false;

		if (nuevo) {
			if (newEquipo.getNombre() != null
					&& newEquipo.getNombre().length() > 0) {
				estado = comprobarNombre(newEquipo.getNombre());

				if (estado) {
					FacesMessages
							.instance()
							.add(
									"El nombre del equipo no está disponible. Inserte otro distinto");
				}
			} else {
				FacesMessages.instance().add(
						"Debe introducir un nombre para el equipo");
			}
		} else {
			if (nombre != null && nombre.length() > 0) {
				estado = comprobarNombre(nombre);
			} else {
				FacesMessages.instance().add(
						"Debe introducir un nombre para el equipo");
			}
		}

		return estado;

	}

	/**
	 * Método que comprueba si ya existe el nombre del equipo introducido
	 * 
	 * @param nombre
	 *            Nombre del equipo a comprobar
	 * @return
	 */
	public boolean comprobarNombre(String nombre) {

		if (!equipo.getNombre().equals(nombre)) {
			return equipoService.existeNombre(nombre);
		} else {
			return false;
		}

		// return equipoService.existeNombre(nombre);
	}

	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void nuevoJugadorParticipante() {
		int cont = 0;
		if (participacion.getM_jugadores() != null) {
			cont = participacion.getM_jugadores().size();
			if (cont < 13) {
				nuevoJug = true;
			} else {
				nuevoJug = false;
				FacesMessages.instance().add(
						"No puede añadir más jugadores al equipo");
			}
		} else {
			nuevoJug = true;
		}
	}

	public boolean guardarParticipaciones() {
		boolean ok = true;

		if (equipo.getM_participaciones() != null
				& equipo.getM_participaciones().size() > 0) {
			Iterator<PartEquipo> it = equipo.getM_participaciones().iterator();
			while (it.hasNext() && ok) {
				PartEquipo p = (PartEquipo) it.next();
				p = partEquipoService.merge(p);
				Set<PartJugador> jugadoresAnt = new HashSet<PartJugador>();
				jugadoresAnt.addAll(p.getM_jugadores());
				if (jugadoresEquipo != null && jugadoresEquipo.size() > 0) {
					jugadoresAnt.removeAll(jugadoresEquipo);
				}
				if (jugadoresAnt != null && jugadoresAnt.size() > 0) {
					if (!eliminaRelacionJugadorEquipo(jugadoresAnt)) {
						ok = false;
					}
				}
				if (jugadoresEquipo != null && jugadoresEquipo.size() > 0) {
					if (!guardaParticipacionesJugador(jugadoresEquipo)) {
						ok = false;
					}
				}
				if (ok) {
					if (!partEquipoService.save(p)) {
						ok = false;
					}
				}
			}
		}

		return ok;
	}

	public boolean eliminaRelacionJugadorEquipo(Set<PartJugador> jugadores) {
		boolean ok = true;
		Iterator<PartJugador> it = jugadores.iterator();
		while (it.hasNext() && ok) {
			PartJugador j = (PartJugador) it.next();
			j.setEquipo(null);
			j.setDorsal(0);
			j.setPosicion(null);
			if (!partJugadorService.save(j)) {
				ok = false;
			}
		}

		if (!ok) {
			FacesMessages
					.instance()
					.add(
							"Ha ocurrido un fallo y no se ha podido eliminar la relación de algún jugador con el equipo.");
		}
		return ok;
	}

	public boolean guardaParticipacionesJugador(Set<PartJugador> jugadores) {
		boolean ok = true;
		Iterator<PartJugador> it = jugadores.iterator();
		while (it.hasNext() && ok) {
			PartJugador j = (PartJugador) it.next();
			if (!partJugadorService.save(j)) {
				ok = false;
			}
		}
		if (!ok) {
			FacesMessages
					.instance()
					.add(
							"Ha ocurrido un fallo y no se ha podido guardar la relación de algún jugador con el equipo.");
		}
		return ok;
	}

	/**
	 * Método para buscar jugadores que incluir en la temporada
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void buscarJugadores() {
		if (!(buscarJug != null && buscarJug.length() > 0)) {
			buscarJug = "";
		}

		jugadoresBus = partJugadorService.buscarParticipacionesTemporada(
				buscarJug, buscarJugEn, participacion.getTemporada());

		// listaPosiciones = posicionService.getList();

	}

	/**
	 * Método para seleccionar un jugador de la lista
	 */
	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void addJugador(PartJugador jugador) {
		if (jugador != null) {
			jugadorSel = jugador;
			listaPosiciones = posicionService.getList();
		}
	}

	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public boolean aceptAdd() {
		if (comprobarJugadorEquipo()) {
			if (posicion != null) {
				if (dorsal != null) {
					jugadorSel.setDorsal(dorsal);
					jugadorSel.setPosicion(posicion);
					jugadorSel.setEquipo(participacion);
					if (jugadoresEquipo != null) {
						jugadoresEquipo.add(jugadorSel);
					} else {
						jugadoresEquipo = new HashSet<PartJugador>();
						jugadoresEquipo.add(jugadorSel);
					}

					jugadorSel = null;
					jugadoresBus = null;
					nuevoJug = false;
					dorsal = null;
					posicion = null;
					buscarJug = null;
					buscarJugEn = 1;

					return true;
				} else {
					FacesMessages.instance().add(
							"Debe introducir un dorsal para el jugador");
					return false;
				}
			} else {
				FacesMessages.instance().add(
						"Debe seleccionar una posicicón para el jugador.");
				return false;
			}
		} else {
			FacesMessages.instance().add(
					"El jugador seleccionado ya está en el equipo");
			return false;
		}
	}

	public void cancelAdd() {
		jugadorSel = null;
	}

	@Begin(join = true, flushMode = FlushModeType.MANUAL)
	public void deleteJugador() {
		jugadorDelete = jugadorItem;
		jugadoresEquipo.remove(jugadorDelete);
	}

	/**
	 * 
	 * @return
	 */
	public boolean comprobarJugadorEquipo() {
		if (jugadoresEquipo != null) {
			for (PartJugador j : jugadoresEquipo) {
				if (j.equals(jugadorSel)) {
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * Método para ver la antigüedad del jugador en el equipo
	 * 
	 * @param jugador
	 * @return
	 */
	public int verAntiguedad(Jugador jugador) {

		int ant = 0;

		for (PartJugador p : jugador.getM_jugadores()) {
			if (p.getTemporada().getAnio().getAnio() <= participacion
					.getTemporada().getAnio().getAnio()) {
				if (p.getEquipo().getEquipo().equals(equipo)) {
					ant++;
				}
			}
		}

		return ant;

	}

	public void limpiar() {
		newEquipo = null;
		equipo = null;
		foto = null;
		participacion = null;
		nextParticipacion = null;
		jugadoresEquipo = null;
		jugadorItem = null;
		nombre = null;
		posicion = null;
		dorsal = null;
	}

	/**
	 * Método para inicializar todos los parámetros al volver al menú de
	 * búsqueda de equipos
	 */
	public void volver() {
		equipo = equipoService.merge(equipo);
		limpiar();
	}

	/**
	 * Método para inicializar todos los parámetros al volver al menú principal
	 */
	@End
	public void menu() {
		limpiar();
		equipoSearch.limpiar();
	}

	/*
	 * getters and setters
	 */

	/**
	 * 
	 * @return
	 */
	public int getModo() {
		return modo;
	}

	/**
	 * 
	 * @param modo
	 */
	public void setModo(int modo) {
		this.modo = modo;
	}

	/**
	 * 
	 * @return
	 */
	public boolean isNuevo() {
		return nuevo;
	}

	/**
	 * 
	 * @param nuevo
	 */
	public void setNuevo(boolean nuevo) {
		this.nuevo = nuevo;
	}

	/**
	 * 
	 * @return
	 */
	public Equipo getEquipo() {
		return equipo;
	}

	/**
	 * 
	 * @param equipo
	 */
	public void setEquipo(Equipo equipo) {
		this.equipo = equipo;
	}

	/**
	 * 
	 * @return
	 */
	public String getNombre() {
		return nombre;
	}

	/**
	 * 
	 * @param nombre
	 */
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	/**
	 * 
	 * @return
	 */
	public PartEquipo getParticipacion() {
		return participacion;
	}

	/**
	 * 
	 * @param participacion
	 */
	public void setParticipacion(PartEquipo participacion) {
		this.participacion = participacion;
	}

	/**
	 * 
	 * @return
	 */
	public PartEquipo getNextParticipacion() {
		return nextParticipacion;
	}

	/**
	 * 
	 * @param nextParticipacion
	 */
	public void setNextParticipacion(PartEquipo nextParticipacion) {
		this.nextParticipacion = nextParticipacion;
	}

	/**
	 * 
	 * @return newEquipo Equipo a dar de alta
	 */
	public Equipo getNewEquipo() {
		return newEquipo;
	}

	/**
	 * 
	 * @param newEquipo
	 *            Equipo
	 */
	public void setNewEquipo(Equipo newEquipo) {
		this.newEquipo = newEquipo;
	}

	/**
	 * 
	 * @return guardado True o false si se guardo correctamente o no
	 */
	public boolean isGuardado() {
		return guardado;
	}

	/**
	 * 
	 * @param guardado
	 */
	public void setGuardado(boolean guardado) {
		this.guardado = guardado;
	}

	/**
	 * 
	 * @return
	 */
	public byte[] getFoto() {
		return foto;
	}

	/**
	 * 
	 * @param foto
	 */
	public void setFoto(byte[] foto) {
		this.foto = foto;
	}

	/**
	 * 
	 * @return
	 */
	public List<AniosDic> getListaAnios() {
		return listaAnios;
	}

	/**
	 * 
	 * @param listaAnios
	 */
	public void setListaAnios(List<AniosDic> listaAnios) {
		this.listaAnios = listaAnios;
	}

	/**
	 * 
	 * @return
	 */
	public List<PartEquipo> getListaParticipaciones() {
		return listaParticipaciones;
	}

	/**
	 * 
	 * @param listaParticipaciones
	 */
	public void setListaParticipaciones(List<PartEquipo> listaParticipaciones) {
		this.listaParticipaciones = listaParticipaciones;
	}

	/**
	 * 
	 * @return
	 */
	public String getBuscarJug() {
		return buscarJug;
	}

	/**
	 * 
	 * @param buscarJug
	 */
	public void setBuscarJug(String buscarJug) {
		this.buscarJug = buscarJug;
	}

	/**
	 * 
	 * @return
	 */
	public int getBuscarJugEn() {
		return buscarJugEn;
	}

	/**
	 * 
	 * @param buscarJugEn
	 */
	public void setBuscarJugEn(int buscarJugEn) {
		this.buscarJugEn = buscarJugEn;
	}

	/**
	 * 
	 * @return
	 */
	public boolean isNuevoJug() {
		return nuevoJug;
	}

	/**
	 * 
	 * @param nuevoJug
	 */
	public void setNuevoJug(boolean nuevoJug) {
		this.nuevoJug = nuevoJug;
	}

	/**
	 * 
	 * @return
	 */
	public List<PartJugador> getJugadoresBus() {
		return jugadoresBus;
	}

	/**
	 * 
	 * @param jugadoresBus
	 */
	public void setJugadoresBus(List<PartJugador> jugadoresBus) {
		this.jugadoresBus = jugadoresBus;
	}

	/**
	 * 
	 * @return
	 */
	public PartJugador getJugadorSel() {
		return jugadorSel;
	}

	/**
	 * 
	 * @param jugadorSel
	 */
	public void setJugadorSel(PartJugador jugadorSel) {
		this.jugadorSel = jugadorSel;
	}

	/**
	 * 
	 * @return
	 */
	public Set<PartJugador> getJugadoresEquipo() {
		return jugadoresEquipo;
	}

	/**
	 * 
	 * @param jugadoresEquipo
	 */
	public void setJugadoresEquipo(Set<PartJugador> jugadoresEquipo) {
		this.jugadoresEquipo = jugadoresEquipo;
	}

	/**
	 * 
	 * @return
	 */
	public PartJugador getJugadorItem() {
		return jugadorItem;
	}

	/**
	 * 
	 * @param jugadorItem
	 */
	public void setJugadorItem(PartJugador jugadorItem) {
		this.jugadorItem = jugadorItem;
	}

	/**
	 * 
	 * @return
	 */
	public PartJugador getJugadorDelete() {
		return jugadorDelete;
	}

	/**
	 * 
	 * @param jugadorDelete
	 */
	public void setJugadorDelete(PartJugador jugadorDelete) {
		this.jugadorDelete = jugadorDelete;
	}

	/**
	 * 
	 * @return
	 */
	public List<PosicionDic> getListaPosiciones() {
		return listaPosiciones;
	}

	/**
	 * 
	 * @param listaPosiciones
	 */
	public void setListaPosiciones(List<PosicionDic> listaPosiciones) {
		this.listaPosiciones = listaPosiciones;
	}

	/**
	 * 
	 * @return
	 */
	public PosicionDic getPosicion() {
		return posicion;
	}

	/**
	 * 
	 * @param posicion
	 */
	public void setPosicion(PosicionDic posicion) {
		this.posicion = posicion;
	}

	/**
	 * 
	 * @return
	 */
	public Integer getDorsal() {
		return dorsal;
	}

	/**
	 * 
	 * @param dorsal
	 */
	public void setDorsal(Integer dorsal) {
		this.dorsal = dorsal;
	}
}
